using Android.App;
using Android.Util;
using DPSBase;
using JmShared;
using NetworkCommsDotNet;
using System;
using System.Collections.Generic;


namespace jivemessenger
{
    public class NetworkConnection
    {

        public Dictionary<string, UserInfo> ConnectedClients { get; set; }
        public EventHandler<OnDisconnectEventArgs> OnDisconnectEventHandler { get; set; }
        public EventHandler<OnReceivedMessageEventArgs> OnReceivedMessage { get; set; }
        public ConnectionInfo MasterConnectionInfo { get; set; }
        public object LockObject = new object();
        public Dictionary<int, KeyValuePair<DateTime, ChatMessage>> SentMessages { get; set; }
        public NetworkConnection()
        {
            SentMessages = new Dictionary<int, KeyValuePair<DateTime, ChatMessage>>();
        }

        /// <summary>
        /// Sends the chatmessage to the server
        /// </summary>
        /// <param name="msg"></param>
        public bool SendMessage(ChatMessage msg)
        {
            if (MasterConnectionInfo == null)
                return false;
            if (MasterConnectionInfo.ConnectionState != ConnectionState.Established)
                return false;
            //bool receiptOk = msg.MessageType != MessageType.Message && msg.MessageType != MessageType.PM;
            try
            {
                //if (msg.MessageType == MessageType.Message || msg.MessageType == MessageType.PM)
                //    receiptOk = ((TCPConnection.GetConnection(MasterConnectionInfo).SendReceiveObject<string>("ChatMessage", "receipt", 2000, msg)) == "1");
                //else
                    TCPConnection.GetConnection(MasterConnectionInfo).SendObject("ChatMessage", msg);
            }
            catch (CommsException err)
            {
                //NetworkComms.Logger.ErrorException("Error writing message", err);
               // receiptOk = false;
                return false;
            }
            return true;// receiptOk;
        }
        public void SendStatusMessage(MessageType mt, string message)
        {
            ChatMessage msg = new ChatMessage { Sender = Client.CurrentUserInfo, MessageType = mt, Message = message };
            SendMessage(msg);
        }

        public void SendStatusMessage(MessageType mt, string message, UserInfo[] targets)
        {
            ChatMessage msg = new ChatMessage { Sender = Client.CurrentUserInfo, MessageType = mt, Message = message, UserInfo = targets };
            SendMessage(msg);
        }
        /// <summary>
        /// Connects to the server
        /// </summary>
        /// <returns></returns>
        public bool Connect()
        {
            try
            {

                if (this.MasterConnectionInfo != null)
                {
                    if (this.MasterConnectionInfo.ConnectionState == ConnectionState.Established)
                        TCPConnection.GetConnection(this.MasterConnectionInfo).CloseConnection(false);
                    MasterConnectionInfo = null;

                }

                if (String.IsNullOrEmpty(StaticSettings.Server))
                {
                    //new AlertDialog.Builder(StaticSettings.GlobalContext)
                    //    .SetMessage("No servers configured")
                    //    .Show();
                    MessageBox.Show("No servers configured");
                    return false;
                }
                string connectionIP = StaticSettings.Server;
                try
                {
                connectionIP =Java.Net.InetAddress.GetByName(StaticSettings.Server).HostAddress;
                }
                catch
                {
                }
                //int port = StaticSettings.ServerPort;

                MasterConnectionInfo = new ConnectionInfo(connectionIP, StaticSettings.ServerPort);
                //NetworkComms.Logger.Info(String.Format("Server address set to {0}", serverAddresses[0]));

                var dataProcessors = new List<DataProcessor>();

                // dataProcessors.Add(DPSManager.GetDataProcessor<SevenZipLZMACompressor.LZMACompressor>());
                dataProcessors.Add(DPSManager.GetDataProcessor<RijndaelPSKEncrypter>());
                NetworkComms.EnablePacketCheckSumValidation = true;
                var dataProcessorOptions = new Dictionary<string, string>();
                RijndaelPSKEncrypter.AddPasswordToOptions(dataProcessorOptions, "fg342ssdfs43232fdfgdg3452fdsgbvcvcblkiuyoaxc");
                DataSerializer dataSerializer = DPSManager.GetDataSerializer<ProtobufSerializer>();
                NetworkComms.DefaultSendReceiveOptions = new SendReceiveOptions(dataSerializer, dataProcessors, dataProcessorOptions);
                NetworkComms.ConnectionEstablishTimeoutMS = 2000;
                NetworkComms.ConnectionAliveTestTimeoutMS = 2000;
                NetworkComms.AppendGlobalIncomingPacketHandler<ChatMessage>("ChatMessage", ProcessMessage);
                NetworkComms.AppendGlobalIncomingPacketHandler<int>("Receipt", ProcessReceipt);
                NetworkComms.AppendGlobalConnectionCloseHandler(client_OnDisconnected);
                NetworkComms.IgnoreUnknownPacketTypes = true;
                TCPConnection.GetConnection(MasterConnectionInfo).EstablishConnection(); //Connect

                //Thread.Sleep(500);

                if (MasterConnectionInfo.ConnectionState != ConnectionState.Established)
                {
                    MessageBox.Show("Connection to " + connectionIP + " failed");
                    return false;
                }

                //var dataProcessors = new List<DataProcessor>();

                //dataProcessors.Add(DPSManager.GetDataProcessor<RijndaelPSKEncrypter>());

                //var dataProcessorOptions = new Dictionary<string, string>();
                //RijndaelPSKEncrypter.AddPasswordToOptions(dataProcessorOptions, "fg342ssdfs43232fdfgdg3452fdsgbvcvcblkiuyoaxc");
                //DataSerializer dataSerializer = DPSManager.GetDataSerializer<ProtobufSerializer>();
                //NetworkComms.DefaultSendReceiveOptions = new SendReceiveOptions(dataSerializer, dataProcessors, dataProcessorOptions);
                //NetworkComms.ConnectionEstablishTimeoutMS = 5000;
                //NetworkComms.ConnectionAliveTestTimeoutMS = 3000;

                //NetworkComms.IgnoreUnknownPacketTypes = true;
                ////  TCPConnection connection=null;
                //try
                //{
                //    //StaticSettings.GlobalContext.RunOnUiThread(() =>
                //    //    {
                //    this.MasterConnectionInfo = null;
                //    this.MasterConnectionInfo = new ConnectionInfo(connectionIP, port);
                //    if (MasterConnectionInfo != null)
                //    {
                //        TCPConnection conn = TCPConnection.GetConnection(this.MasterConnectionInfo);
                //        if (conn != null && conn.ConnectionInfo.IsConnectable)
                //            conn.EstablishConnection();
                //    }

                //    //});


                //}
                //catch (ObjectDisposedException e)
                //{
                //    Log.Error("JiveMessenger", "Error getting tcp connection" + e);
                //}
                //catch (Exception err)
                //{
                //    // MessageBox.Show("Connection to " + connectionIP + " failed");
                //    Log.Error("JiveMessenger", "Error getting tcp connection" + err);
                //}
                ////if (connection != null)
                ////    connection.EstablishConnection(); //Connect



                //if (this.MasterConnectionInfo.ConnectionState != ConnectionState.Established)
                //{
                //    //NetworkComms.RemoveGlobalConnectionCloseHandler(client_OnDisconnected);
                //    //NetworkComms.RemoveGlobalIncomingPacketHandler("ChatMessage");
                //    MessageBox.Show("Connection to " + connectionIP + " failed");
                //    return false;
                //}

                //NetworkComms.AppendGlobalIncomingPacketHandler<ChatMessage>("ChatMessage", this.ProcessMessage);
                //NetworkComms.AppendGlobalConnectionCloseHandler(this.client_OnDisconnected);
                UserInfo user = new UserInfo
                    {
                        UserName = StaticSettings.Username,
                        ClientStatus = ClientStatus.Available,
                        ID = StaticMethods.GetUniqueId()
                    };
                ChatMessage msg = new ChatMessage
                    {
                        MessageType = MessageType.Login,
                        Message = StaticMethods.ObjectToString<LoginInfo>(new LoginInfo
                            {
                                Username = StaticSettings.Username.ToLower(),
                                Password = StaticMethods.EncodePassword(StaticSettings.Password)
                            }),
                        Sender = user
                    };
                Client.CurrentUserInfo = user;
                this.SendMessage(msg);
                return true;
            }
            catch (Exception err)
            {
                //NetworkComms.RemoveGlobalConnectionCloseHandler(client_OnDisconnected);
                //NetworkComms.RemoveGlobalIncomingPacketHandler("ChatMessage");
                return false;
            }

            //}
            //return true;
        }
        private void ProcessReceipt(PacketHeader packetheader, Connection connection, int incomingobject)
        {
            lock (LockObject)
                this.SentMessages.Remove(incomingobject);
        }
        /// <summary>
        /// Process received ChatMessage objects
        /// </summary>
        /// <param name="header"></param>
        /// <param name="connection"></param>
        /// <param name="msg"></param>
        private void ProcessMessage(PacketHeader header, Connection connection, ChatMessage msg)
        {
            //connection.SendObject("reply", "1");
            OnReceivedMessage(this, new OnReceivedMessageEventArgs(header, connection, msg));
        }
        /// <summary>
        /// Triggers on disconnect from the server.
        /// </summary>
        private void client_OnDisconnected(Connection connection)
        {
            NetworkComms.RemoveGlobalConnectionCloseHandler(client_OnDisconnected);
            NetworkComms.RemoveGlobalIncomingPacketHandler("ChatMessage");
            if (OnDisconnectEventHandler != null)
                OnDisconnectEventHandler(this, new OnDisconnectEventArgs(connection));
        }
        public class OnDisconnectEventArgs : EventArgs
        {
            Connection Connection { get; set; }
            public OnDisconnectEventArgs(Connection conn)
            {
                this.Connection = conn;
            }
        }
        public class OnReceivedMessageEventArgs : EventArgs
        {
            public Connection Connection { get; set; }
            public PacketHeader Header { get; set; }
            public ChatMessage Msg { get; set; }
            public OnReceivedMessageEventArgs(PacketHeader header, Connection conn, ChatMessage msg)
            {
                this.Header = header;
                this.Connection = conn;
                this.Msg = msg;
            }
        }

    }
}
